package com.orcs.leefei.utils.kotlin

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Parcelable
import android.support.v4.app.ActivityCompat
import android.support.v4.app.ActivityOptionsCompat
import android.support.v4.app.Fragment as SupportFragment
import android.support.v7.app.AppCompatActivity
import android.view.View
import java.io.Serializable

/**
 * Created by FeiLee on 2016/12/26 11:16.
 */


inline fun <reified T : Activity> Activity.supportStartActivity(vararg params: Pair<String, Any?>) {
    Internals.internalStartActivity(this, T::class.java, params);
}

//inline fun <reified T : Activity> Activity.supportStartActivity(intent: Intent, vararg params: Pair<String, Any?>) {
//    Internals.internalStartActivity(this, T::class.java, intent, params);
//}

inline fun <reified T : Activity> Activity.supportStartActivity(options: Bundle?, vararg params: Pair<String, Any?>) {
    Internals.internalStartActivity(this, T::class.java, options, params);
}

inline fun <reified T : AppCompatActivity> SupportFragment.supportStartActivity(vararg params: Pair<String, Any?>) {
    Internals.internalStartActivity(activity, T::class.java, params);
}

//inline fun <reified T : AppCompatActivity> Fragment.supportStartActivity(intent: Intent, vararg params: Pair<String, Any?>) {
//    Internals.internalStartActivity(activity, T::class.java, intent, params);
//}

inline fun <reified T : Activity> SupportFragment.supportStartActivity(intent: Intent, options: Bundle?, vararg params: Pair<String, Any?>) {
    Internals.internalStartActivity(activity, T::class.java, intent, params);
}

inline fun AppCompatActivity.supportFinishAfterTransition() {
    ActivityCompat.finishAfterTransition(this)
}

inline fun SupportFragment.supportFinishAfterTransition() {
    ActivityCompat.finishAfterTransition(activity)
}

object Internals {

    @JvmStatic
    fun internalStartActivity(ctx: Activity, activity: Class<out Activity>, params: Array<out Pair<String, Any?>>) {
        ActivityCompat.startActivity(ctx, createIntent(ctx, activity, params), createOptions(ctx, params))
    }

    @JvmStatic
    fun internalStartActivity(ctx: Activity, activity: Class<out Activity>, intent: Intent, params: Array<out Pair<String, Any?>>) {
        ActivityCompat.startActivity(ctx, createIntent(ctx, activity, intent, params), createOptions(ctx, params))
    }

    @JvmStatic
    fun internalStartActivity(ctx: Activity, activity: Class<out Activity>, options: Bundle?, params: Array<out Pair<String, Any?>>) {
        ActivityCompat.startActivity(ctx, createIntent(ctx, activity, params), options)
    }

    private fun createOptions(activity: Activity, params: Array<out Pair<String, Any?>>): Bundle? {
        val sharedElements = mutableListOf<android.support.v4.util.Pair<View, String>>()
        params.forEach {
            val second = it.second
            if (second !== null && second is View) {
                sharedElements.add(android.support.v4.util.Pair(second, it.first))
            }
        }
        return ActivityOptionsCompat.makeSceneTransitionAnimation(
                activity,
                *sharedElements.toTypedArray()
        ).toBundle()
    }

    @JvmStatic
    fun <T> createIntent(ctx: Context, clazz: Class<out T>, params: Array<out Pair<String, Any?>>): Intent {
        val intent = Intent(ctx, clazz)
        if (params.isNotEmpty()) intentOf(intent, params)
        return intent
    }

    @JvmStatic
    fun <T> createIntent(ctx: Context, clazz: Class<out T>, intent: Intent, params: Array<out Pair<String, Any?>>): Intent {
        if (params.isNotEmpty()) intentOf(intent, params)
        return intent
    }
}

private fun intentOf(intent: Intent, params: Array<out Pair<String, Any?>>): Intent {
    params.forEach {
        val value = it.second
        if (value != null) {
            when (value) {
                is Int -> intent.putExtra(it.first, value)
                is Long -> intent.putExtra(it.first, value)
                is CharSequence -> intent.putExtra(it.first, value)
                is String -> intent.putExtra(it.first, value)
                is Float -> intent.putExtra(it.first, value)
                is Double -> intent.putExtra(it.first, value)
                is Char -> intent.putExtra(it.first, value)
                is Short -> intent.putExtra(it.first, value)
                is Boolean -> intent.putExtra(it.first, value)
                is Serializable -> intent.putExtra(it.first, value)
                is Bundle -> intent.putExtra(it.first, value)
                is Parcelable -> intent.putExtra(it.first, value)
                is Array<*> -> when {
                    value.isArrayOf<CharSequence>() -> intent.putExtra(it.first, value)
                    value.isArrayOf<String>() -> intent.putExtra(it.first, value)
                    value.isArrayOf<Parcelable>() -> intent.putExtra(it.first, value)
                    value.isArrayOf<View>() -> {
                    }
                    else -> throw IllegalArgumentException(
                            "Intent extra ${it.first} has wrong type ${value.javaClass.name}")
                }
                is IntArray -> intent.putExtra(it.first, value)
                is LongArray -> intent.putExtra(it.first, value)
                is FloatArray -> intent.putExtra(it.first, value)
                is DoubleArray -> intent.putExtra(it.first, value)
                is CharArray -> intent.putExtra(it.first, value)
                is ShortArray -> intent.putExtra(it.first, value)
                is BooleanArray -> intent.putExtra(it.first, value)
                is View -> {/*do nothing*/
                }
                else -> throw IllegalArgumentException("Unsupported bundle component ${it.first}: $value")
            }
        }

    }

    return intent
}
//fun Any?.flags(flag: Int, vararg flags: Int): Int {
//    var orFlags = flag;
//    for (i in flags) {
//        orFlags = orFlags or i
//    }
//    return orFlags
//}
//
//inline  fun <reified T : Activity> Activity.start() {
//    supportStartActivity(intent<T>())
//}
//
//inline  fun <reified T : Activity> Activity.start(flags: Int) {
//    this.supportStartActivity(intent<T>(flags))
//}
//
//inline  fun <reified T: Activity> Activity.start(extras: Bundle) {
//    this.supportStartActivity(intent<T>(extras))
//}
//
//inline  fun <reified T: Activity> Activity.start(extras: Bundle, flags: Int) {
//    this.supportStartActivity(intent<T>(extras, flags))
//}
//
//
//inline  fun <reified T : Activity> Activity.startForResult(requestCode: Int) {
//    this.startActivityForResult(intent<T>(), requestCode)
//}
//
//inline  fun <reified T : Activity> Activity.startForResult(
//        requestCode: Int, flags: Int) {
//    this.startActivityForResult(intent<T>(flags), requestCode)
//}
//
//inline  fun <reified T : Activity> Activity.startForResult(
//        extras: Bundle, requestCode: Int) {
//    this.startActivityForResult(intent<T>(extras), requestCode)
//}
//
//inline  fun <reified T : Activity> Activity.startForResult(
//        extras: Bundle, requestCode: Int, flags: Int) {
//    this.startActivityForResult(intent<T>(extras, flags), requestCode)
//}
//
//inline  fun <reified T : Activity> Service.start() {
//    this.supportStartActivity(intent<T>(Intent.FLAG_ACTIVITY_NEW_TASK))
//}
//
//inline  fun <reified T : Activity> Service.start(flags: Int) {
//    this.supportStartActivity(intent<T>(flags))
//}
//
//inline  fun <reified T: Activity> Service.start(extras: Bundle) {
//    this.supportStartActivity(intent<T>(extras, Intent.FLAG_ACTIVITY_NEW_TASK))
//}
//
//inline  fun <reified T: Activity> Service.start(extras: Bundle, flags: Int) {
//    this.supportStartActivity(intent<T>(extras, flags))
//}
//
//inline  fun <reified T: Service> Context.start() {
//    this.startService(intent<T>())
//}
//
//inline  fun <reified T: Service> Context.start(flags: Int) {
//    this.startService(intent<T>(flags))
//}
//
//inline  fun <reified T: Service> Context.start(extras: Bundle) {
//    this.startService(intent<T>(extras))
//}
//
//inline  fun <reified T: Service> Context.start(extras: Bundle, flags: Int) {
//    this.startService(intent<T>(extras, flags))
//}
//
//inline  fun <reified T: Context> Context.intent(): Intent {
//    return Intent(this, T::class.java)
//}
//
//inline  fun <reified T: Context> Context.intent(flags: Int): Intent {
//    val intent = intent<T>()
//    intent.setFlags(flags)
//    return intent
//}
//
//inline  fun <reified T: Context> Context.intent(extras: Bundle): Intent {
//    return intent<T>(extras, 0)
//}
//
//inline  fun <reified T: Context> Context.intent(extras: Bundle, flags: Int): Intent {
//    val intent = intent<T>(flags)
//    intent.putExtras(extras)
//    return intent
//}
//
//inline fun WebIntent(url: String): Intent {
//    return if (Patterns.WEB_URL.matcher(url).matches()) {
//        Intent(Intent.ACTION_VIEW, Uri.parse(url))
//    } else throw IllegalArgumentException("Passed url: $url does not match URL pattern.")
//}